<?php

namespace app\api\validate;


use common\exception\ParameterException;
use common\exception\ExceptionEmun;
use common\exception\SystemException;
use think\Validate;

/**
 * Class BaseValidate
 * 验证类的基类
 */
class BaseValidate extends Validate
{

    protected $ret_dat = [];

    /**
     * BaseValidate constructor.
     * @param array $rules
     * @param array $message
     * @param array $field
     */
    public function __construct(array $rules = [], array $message = [], array $field = [])
    {
        parent::__construct($rules, $message, $field);
        $this->ret_dat['input'] = input();
    }

    /**
     * 获取返回异常的data
     * @return array
     */
    public function getRetDat()
    {
        return $this->ret_dat;
    }

    /**
     * 添加返回异常的data
     * @param array $ret_dat
     */
    public function addRetDat($ret_dat)
    {
        $this->ret_dat = array_merge($this->ret_dat, $ret_dat);
    }

    /**
     * 检测验证类规则
     * @param $data
     * @param string $scene
     * @param string $msg 可以不填,不填使用TP的提示语
     * @param array $ret_data 可以不填,不填使用默认异常返回数据
     * @return bool
     * @throws BaseException
     */
    public function runCheck($data, $rules = '', $scene = '')
    {
        $scene ?? $this->getScene($scene);
        if (false == $this->check($data, $this->rule, $scene)) {
            $msg = is_array($this->error) ? implode(';', $this->error) : $this->error;
            ExceptionEmun::throwException(SystemException::INVALID_PARAMETER, $msg, $this->ret_dat);
        }
        return true;
    }

    /**
     * 注入规则
     * @param Array $rules <br>[filed=>[rule1,rule2,...]]<br>[filed=>rule1]
     * @param Array $scene 设置了场景的话会把新加的内容加入场景
     * @return Array $this->rule
     */
    public function addRule($rules, $scene = '')
    {
        foreach ($rules as $key => $rule) {
            $insert = 1;
            foreach ($this->rule as $source_key => $source_value) {
                if (preg_match("/^{$key}\W*\w*$/", $source_key)) {
                    if (is_array($rule)) {
                        foreach ($rule as $rule_unit) {
                            $this->rule[$source_key][] = $rule_unit;
                        }
                    } else {
                        if (in_array($rule, $this->rule[$source_key]) == false) {
                            $this->rule[$source_key][] = $rule;
                        }
                    }
                    $insert = 0;
                }
            }
            if ($insert) {
                $this->rule[$key] = $rule;
            }
            if (!empty($scene)) {
                if (strpos($key, '|')) {
                    // 字段|描述 用于指定属性名称
                    list($key, $title) = explode('|', $key);
                }
                $this->setScene($scene, $key);
            }
        }
        return $this->rule;
    }

    /**
     * 移除规则
     * @param Array $rules <br>[filed=>[rule1,rule2,...]]<br>[filed=>rule1]
     * @return Array $this->rule
     */
    public function delRule($rules, $scene = '')
    {
        foreach ($rules as $key => $rule) {
            foreach ($this->rule as $source_key => $source_value) {
                if (preg_match("/^{$key}\W*\w*$/", $source_key)) {
                    if (is_array($rule)) {
                        foreach ($rule as $rule_unit) {
                            $index = array_search($rule_unit, $this->rule[$source_key]);
                            if ($index !== false) {
                                unset($this->rule[$source_key][$index]);
                            }
                        }
                    } else {
                        if ($index = array_search($rule, $this->rule[$source_key])) {
                            unset($this->rule[$source_key][$index]);
                        }
                    }
                }
            }
            if (!empty($scene)) {
                if (strpos($key, '|')) {
                    // 字段|描述 用于指定属性名称
                    list($key, $title) = explode('|', $key);
                }
                $this->setScene($scene, $key);
            }
        }
        return $this->rule;
    }

    /**
     * 获取scene,设置only,主要配合addRule和delRule使用<br>
     * $this->only为空时使用this->scene
     * @param string $scene_name
     * @return array
     */
    protected function getScene($scene_name = '')
    {
        parent::getScene($scene_name);
        if (empty($this->only) && isset($this->scene[$scene_name])) {
            $temp = $this->scene[$scene_name];
            if (is_string($temp)) {
                $temp = explode(',', $temp);
            }
            $this->only = $temp;
        }
        return $this->scene[$scene_name];
    }

    /**
     * 设置使用场景,主要配合addRule和delRule使用
     * @param $scene
     * @param $field
     * @param $del
     */
    protected function setScene($scene_name, $field, $del = 0)
    {
        //场景不存在就创建场景
        if (empty($this->scene[$scene_name])) {
            $this->scene[$scene_name] = [];
        }
        //添加
        if (!in_array($field, $this->scene[$scene_name])) {
            $this->scene[$scene_name][] = $field;
        }
        //删除
        if (!empty($del)) {
            $index = array_search($field, $this->scene[$scene_name]);
            if ($index !== false) {
                unset($this->scene[$scene_name][$index]);
            }
        }
        return $this->scene[$scene_name];
    }

    /**
     * 获取rule
     * @return array
     */
    public function getRule()
    {
        return $this->rule;
    }

    /**
     * 正整数检测
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool|string
     */
    protected function isPositiveInteger($value, $rule = '', $data = [], $field = '', $describe)
    {
        if (is_positive_int($value)) {
            return true;
        }
        return $describe . '必须是正整数';
    }

    /**
     * 非空检测
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool|string
     */
    protected function isNotEmpty($value, $rule = '', $data = [], $field = '', $describe)
    {
        if (empty($value)) {
            return $describe . '不允许为空';
        } else {
            return true;
        }
    }

    /**
     * 字符串非空检测
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool|string
     */
    protected function isNotEmptyString($value, $rule = '', $data = [], $field = '', $describe)
    {
        if (is_empty_string($value)) {
            return $describe . '不允许为空';
        } else {
            return true;
        }
    }

    /**
     * 手机号检测
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool|string
     */
    protected function isMobile($value, $rule = '', $data = [], $field = '', $describe)
    {
        $rule = '^1\d{10}$^';
        $result = preg_match($rule, $value);
        if ($result) {
            return true;
        } else {
            return '非法' . $describe;
        }
    }
}